package com.qyb.base.java8.chap5;



import com.qyb.base.java8.bean.Dish;

import java.util.Arrays;
import java.util.List;
import java.util.Optional;

import static com.qyb.base.java8.bean.Dish.menu;

/*
    归约
        将流中所有元素反复结合起来，得到一个值，比如一个Integer。这样的查询可以被归类为归约操作（将流归约成一个值）。


 */
public class Reducing{

    public static void demo1(){
        /*
        reduce接受两个参数：
             一个初始值，这里是0；
             一个BinaryOperator<T>来将两个元素结合起来产生一个新值，这里我们用的是lambda (a, b) -> a + b。
         */
        //求和
        List<Integer> numbers = Arrays.asList(3,4,5,1,2);
        int sum = numbers.stream().reduce(0, (a, b) -> a + b);
        System.out.println(sum);
        int sum2 = numbers.stream().reduce(0, Integer::sum);
        System.out.println(sum2);

        /*
        使用流来对所有的元素并行求和时，你的
        代码几乎不用修改：stream()换成了parallelStream()。
        int sum = numbers.parallelStream().reduce(0, Integer::sum);
        但要并行执行这段代码也要付一定代价，我们稍后会向你解释：传递给reduce的Lambda
        不能更改状态（如实例变量），而且操作必须满足结合律才可以按任意顺序执行。
        */
        /*
        无初始值
        reduce还有一个重载的变体，它不接受初始值，但是会返回一个Optional对象：
        Optional<Integer> sum = numbers.stream().reduce((a, b) -> (a + b));
        为什么它返回一个Optional<Integer>呢？考虑流中没有任何元素的情况。reduce操作无
        法返回其和，因为它没有初始值。这就是为什么结果被包裹在一个Optional对象里，以表明和
        可能不存在。
        */
        //最大值
        int max = numbers.stream().reduce(0, (a, b) -> Integer.max(a, b));
        System.out.println(max);

        //最小值
        Optional<Integer> min = numbers.stream().reduce(Integer::min);
        min.ifPresent(System.out::println);

        int calories = menu.stream()
                           .map(Dish::getCalories)
                           .reduce(0, Integer::sum);
        System.out.println("Number of calories:" + calories);

        /*
        流操作：无状态和有状态
        诸如map或filter等操作会从输入流中获取每一个元素，并在输出流中得到0或1个结果。
        这些操作一般都是无状态的：它们没有内部状态（假设用户提供的Lambda或方法引用没有内部可变状态）。
        但诸如reduce、sum、max等操作需要内部状态来累积结果。


        操 作     类 型  返回类型  使用的类型/函数式接口  函数描述符
        filter    中间  Stream<T>  Predicate<T>  T -> boolean
        distinct  中间  Stream<T>
        (有状态-无界)
         skip  中间  Stream<T> long
        (有状态-有界)
        limit  中间 Stream<T> long
        (有状态-有界)
        map  中间  Stream<R>  Function<T, R>  T -> R
        flatMap  中间  Stream<R>  Function<T, Stream<R>>  T -> Stream<R>
        sorted  中间 Stream<T>
        (有状态-无界)
        Comparator<T>  (T, T) -> int
        anyMatch  终端  boolean  Predicate<T>  T -> boolean
        noneMatch  终端  boolean  Predicate<T>  T -> boolean
        allMatch  终端  boolean  Predicate<T>  T -> boolean
        findAny  终端  Optional<T>
        findFirst  终端  Optional<T>
        forEach  终端  void  Consumer<T>  T -> void
        collect  终端  R  Collector<T, A, R>
        reduce  终端   Optional<T> BinaryOperator<T>  (T, T) -> T
        (有状态-有界)
        count  终端  long
        */
    }
}
